﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;

namespace D3crft {
    class cMain {

        // Windows
        Windows.wMain oMainWindow;
        Windows.wLoadProgress oLoadingWindow;
        Windows.wNewCharacter oNewCharacterWindow;
        Windows.wStatChooser oStatChooserWindow;

        Characters.ocCharacterManager oCharacterManager = new Characters.ocCharacterManager();


        private Characters.ClassObjects.ocCharacter oSelectedCharacter;
        //private Characters.ClassObjects.ocCharacter oEditingCharacter;

        private bool flag_ForwardCharacterManagerInfoToLoadingWindow = false;
        private bool flag_StartupRoutineInProgress = false;

        // ####################################################
        // #####    Object Initialization
        // ####################################################
        #region Object Initialization

        public cMain() {
            do_Initialize();
            do_Preset();
            do_Startup();
        }

        ~cMain() {
            do_Finalize();
        }

        private void do_Initialize() {

        }

        private void do_Preset() {
            Utilities.Settings.scSettingsAccess.Flag_Set_AutoSave(true);
            Utilities.Settings.scSettingsAccess.Settings_Load(System.AppDomain.CurrentDomain.BaseDirectory + "\\" + Properties.Resources.Settings_Filename);

#if DEBUG
            Utilities.Logging.scLoggingAccess.Start_TimedHybridLog(System.AppDomain.CurrentDomain.BaseDirectory + Properties.Resources.Log_Filename, 5);
#else
            Utilities.Logging.scLoggingAccess.Setting_DefaultFilename = System.AppDomain.CurrentDomain.BaseDirectory + Properties.Resources.Log_Filename;
#endif

            oCharacterManager.evCharacterLoadingProcess_Started += new Characters.ocCharacterManager.delCharacterLoadingProcessHandler(ev_oCharacterManager_CharacterLoadProcess_Started);
            oCharacterManager.evCharacterLoadingProcess_PreloadUpdate += new Characters.ocCharacterManager.delCharacterLoadingProcessHandler(ev_oCharacterManager_CharacterLoadProcess_PreloadUpdate);
            oCharacterManager.evCharacterLoadingProcess_PostloadUpdate += new Characters.ocCharacterManager.delCharacterLoadingProcessHandler(ev_oCharacterManager_CharacterLoadProcess_PostloadUpdate);
            oCharacterManager.evCharacterLoadingProcess_Finished += new Characters.ocCharacterManager.delCharacterLoadingProcessHandler(ev_oCharacterManager_CharacterLoadProcess_Finished);
            oCharacterManager.SetCharacterPath(System.AppDomain.CurrentDomain.BaseDirectory + "\\characters");
        }

        private void do_Startup() {
            do_EnterStartupRoutine();
        }

        private void do_Finalize() {
            if (oSelectedCharacter != null) {
                Utilities.Settings.scSettingsAccess.Setting_Set("gui.character.lastselectedname", oSelectedCharacter.sName);
                Utilities.Settings.scSettingsAccess.Setting_Set("gui.character.lastselectedclass", Characters.ClassObjects.ocCharacter.GetClassString(oSelectedCharacter.eClass));

            }
            else {
                if (Utilities.Settings.scSettingsAccess.Setting_Get("gui.character.lastselectedname") != null) Utilities.Settings.scSettingsAccess.Setting_Delete("gui.character.lastselectedname");
                if (Utilities.Settings.scSettingsAccess.Setting_Get("gui.character.lastselectedclass") != null) Utilities.Settings.scSettingsAccess.Setting_Delete("gui.character.lastselectedclass");
            }
            Utilities.Settings.scSettingsAccess.Settings_Save(System.AppDomain.CurrentDomain.BaseDirectory + "\\" + Properties.Resources.Settings_Filename);
        }

        #endregion

        // ####################################################
        // #####    Private Functions
        // ####################################################
        #region Private Functions

        private void do_EnterStartupRoutine() {
            flag_ForwardCharacterManagerInfoToLoadingWindow = true;
            flag_StartupRoutineInProgress = true;
            oMainWindow = new Windows.wMain();
            oLoadingWindow = new Windows.wLoadProgress();
            oLoadingWindow.Unloaded += new System.Windows.RoutedEventHandler(ev_oLoadingWindow_Unloaded);
            oLoadingWindow.Show();

            oCharacterManager.ReloadCharacters();
        }

        private void do_FinishStartupRoutine() {
            string sTemp;
            // windows
            oMainWindow.evNewCharacterClicked += new Characters.ClassObjects.ocCharacter.CharacterEventHandler(ev_oMainWindow_NewCharacterClicked);
            oMainWindow.evCharacterSelectionChanged += new Characters.ClassObjects.ocCharacter.CharacterEventHandler(ev_oMainWindow_CharacterSelectionChanged);
            oMainWindow.evCharacterDeleted += new Characters.ClassObjects.ocCharacter.CharacterEventHandler(ev_oMainWindow_CharacterDeleted);
            oMainWindow.evCharacterStatChanged += ev_oMainWindow_CharacterStatChanged;
            oMainWindow.evItems_ItemEditor_AddClicked += new Windows.UserControls.ucItemEditor.delAddStatHandler(ev_oMainWindow_Items_ItemEditor_AddClicked);
            oMainWindow.evItems_ItemEditor_StatClicked += new Windows.UserControls.ucItemEditor.delEditStatHandler(ev_oMainWindow_Items_ItemEditor_StatClicked);
            oMainWindow.evItems_ItemEditor_ItemStatsChanged += new Windows.UserControls.ucItemEditor.ItemDPSHandler(ev_oMainWindow_Items_ItemEditor_ItemStatsChanged);
            oMainWindow.evItems_ItemEditor_NonItemizedCharacterChanged += new Characters.ClassObjects.ocCharacter.CharacterEventHandler(ev_oMainWindow_Items_ItemEditor_NonItemizedCharacterChanged);

            List<Characters.ClassObjects.ocCharacter> clChars = oCharacterManager.GetCharacterList();

            for (int i = 0; i < clChars.Count; i++) {
                if (clChars[i].sName == Utilities.Settings.scSettingsAccess.Setting_Get("gui.character.lastselectedname")) {
                    sTemp = Utilities.Settings.scSettingsAccess.Setting_Get("gui.character.lastselectedclass");
                    if (sTemp != null) {
                        if (Characters.ClassObjects.ocCharacter.GetClassString(clChars[i].eClass).ToLower() == Utilities.Settings.scSettingsAccess.Setting_Get("gui.character.lastselectedclass").ToLower()) {
                            oSelectedCharacter = clChars[i];
                        }
                    }
                }
            }

            oMainWindow.Show();
            do_UpdateGUICharacterList(true);
            if (oSelectedCharacter != null) {
               // oMainWindow.UpdateItemDPSComparison(null, 0.0f, 0.0f);
            }
        }

        #endregion

        // ####################################################
        // #####    GUI Interaction
        // ####################################################
        #region GUI Interaction

        // Main Window

        private void do_UpdateGUICharacterList(bool bRetainSelection) {
            List<Characters.ClassObjects.ocCharacter> clCharacters;
            string sKeepName = "";
            string iCharID = null;
            Characters.ClassObjects.ocCharacter.eCharacterClass eKeepClass = Characters.ClassObjects.ocCharacter.eCharacterClass.Unknown;


            if (bRetainSelection) {
                if (oSelectedCharacter != null) {
                    sKeepName = oSelectedCharacter.sName;
                    eKeepClass = oSelectedCharacter.eClass;
                }
            }
            oSelectedCharacter = null;
            oMainWindow.ClearCharacterList();
            clCharacters = oCharacterManager.GetCharacterList();
            for (int i = 0; i < clCharacters.Count; i++) {
                oMainWindow.AddCharacterToList(clCharacters[i]);

                if (bRetainSelection) {
                    if (clCharacters[i].sName.ToLower() == sKeepName.ToLower()) {
                        if (clCharacters[i].eClass == eKeepClass) {
                            iCharID = clCharacters[i].sID;
                        }
                    }
                }

                
            }
            if (bRetainSelection) if (iCharID != null) oMainWindow.SelectCharacter(oCharacterManager.GetCharacter(iCharID));
        }

        private void ev_oMainWindow_NewCharacterClicked(object oSender, Characters.ClassObjects.CharacterEventArgs oCharacterEventArgs) {
            if (oNewCharacterWindow == null || !oNewCharacterWindow.IsVisible) {
                oNewCharacterWindow = new Windows.wNewCharacter();
                oNewCharacterWindow.Owner = oMainWindow;
                oNewCharacterWindow.evNewNameClassComboEntered += new Windows.wNewCharacter.delUniqCharComboHandler(ev_oNewCharacterWindow_NewNameClassComboEntered);
                oNewCharacterWindow.evCreateClicked += new Windows.wNewCharacter.delUniqCharComboHandler(ev_oNewCharacterWindow_CreateClicked);
                oNewCharacterWindow.Unloaded += new System.Windows.RoutedEventHandler(ev_oNewCharacterWindow_Unloaded);
                oMainWindow.QueueShadowOverlay(1);
                oNewCharacterWindow.Show();
            }
        }

        private void ev_oMainWindow_CharacterSelectionChanged(object oSender, Characters.ClassObjects.CharacterEventArgs oCharacterEventArgs) {
#if DEBUG
            Utilities.Logging.scLoggingAccess.Log("Character selection changed: " + oCharacterEventArgs.sCharacterID + ":" + oCharacterEventArgs.sCharacterName);
#endif
            Characters.ClassObjects.ocCharacter oTempChar = oCharacterManager.GetCharacter(oCharacterEventArgs.sCharacterID);
            if (oTempChar != null) {
                oSelectedCharacter = oTempChar;
                oMainWindow.UpdateDPSPreview(oSelectedCharacter.sName, (Characters.scCharacterAnalysis.GetCharacterDPS(oSelectedCharacter) / 1000.0f).ToString("N1", CultureInfo.InvariantCulture).Replace(",", "") + "k");
                oMainWindow.UpdateSelectedCharacter(oTempChar);
                //System.Windows.MessageBox.Show(oTempChar.sID);
                //if (System.Windows.MessageBox.Show("test", "mehr", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Question) != System.Windows.MessageBoxResult.Yes) {
                //    oMainWindow.SelectCharacter("1002");
                //}
                
            }
        }

        private void ev_oMainWindow_CharacterDeleted(object oSender, Characters.ClassObjects.CharacterEventArgs oCharacterEventArgs) {
            if (oCharacterEventArgs.sCharacterID == oSelectedCharacter.sID) {
                if (oCharacterManager.RemoveCharacter(oCharacterEventArgs.sCharacterID)) {
                    oSelectedCharacter = null;
                    do_UpdateGUICharacterList(false);
                }
                else {
                    System.Windows.MessageBox.Show("Error deleting character '" + oCharacterEventArgs.sCharacterName + "'.", "D3Crft", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
                }
            }

        }

        private void ev_oMainWindow_CharacterStatChanged(object oSender, EventArgs oEventArgs) {
#if DEBUG
            Utilities.Logging.scLoggingAccess.Log("Character stats changed: " + oSelectedCharacter.sID + ":" + oSelectedCharacter.sName);
#endif
            oMainWindow.UpdateSelectedCharacterStats(oSelectedCharacter);
            oCharacterManager.EditCharacter(oSelectedCharacter.sID, oSelectedCharacter);
        }

        private void ev_oMainWindow_Items_ItemEditor_AddClicked(object oSender, Windows.UserControls.ucItemEditor.delStatReturnHandler oReturnHandler) {
            if (oStatChooserWindow == null) {
                oStatChooserWindow = new Windows.wStatChooser(oSender, oReturnHandler);
                oStatChooserWindow.Owner = oMainWindow;
                oStatChooserWindow.Unloaded += new System.Windows.RoutedEventHandler(ev_oStatChooserWindow_Unloaded);
                oMainWindow.QueueShadowOverlay(1);
                oStatChooserWindow.Show();
            }
        }

        private void ev_oMainWindow_Items_ItemEditor_StatClicked(object oSender, int iStatID, float fStatAmmount, int iStatIndex, Windows.UserControls.ucItemEditor.delStatReturnHandler oReturnHandler) {
            if (oStatChooserWindow == null) {
                oStatChooserWindow = new Windows.wStatChooser(oSender, iStatID, fStatAmmount,iStatIndex, oReturnHandler);
                oStatChooserWindow.Owner = oMainWindow;
                oStatChooserWindow.Unloaded += new System.Windows.RoutedEventHandler(ev_oStatChooserWindow_Unloaded);
                oMainWindow.QueueShadowOverlay(1);
                oStatChooserWindow.Show();
            }
        }

        private void ev_oMainWindow_Items_ItemEditor_ItemStatsChanged(object oSender, Windows.UserControls.ItemDPSEventArgs eaItemDPS) {
#if DEBUG
            Utilities.Logging.scLoggingAccess.Log("Item stats changed: " + eaItemDPS.fBaseDPS.ToString() + ":" + eaItemDPS.fItemDPS.ToString());
#endif
            oMainWindow.UpdateItemComparisonDPS(oSender, eaItemDPS.fBaseDPS, eaItemDPS.fItemDPS);
        }

        private void ev_oMainWindow_Items_ItemEditor_NonItemizedCharacterChanged(object oSender, Characters.ClassObjects.CharacterEventArgs eaCharacter) {
#if DEBUG
            Utilities.Logging.scLoggingAccess.Log("Non-itemized character updated: " + eaCharacter.sCharacterID + ":" + eaCharacter.sCharacterName);
#endif
            oMainWindow.UpdateItemEditorNonItemizedCharacter(oSender, eaCharacter.oCharacter);
        }

        // Others

        private void ev_oNewCharacterWindow_NewNameClassComboEntered(string sCharName, string sCharClass) {
            Characters.ClassObjects.ocCharacter.eCharacterClass eClass = Characters.ClassObjects.ocCharacter.GetClassEnumeration(sCharClass);
            if (oCharacterManager.IsNameClassCombinationUnique(sCharName, eClass)) {
                oNewCharacterWindow.AllowCreate();
            }
            else {
                oNewCharacterWindow.DenyCreate();
            }
        }

        private void ev_oNewCharacterWindow_CreateClicked(string sCharName, string sCharClass) {
            Characters.ClassObjects.ocCharacter.eCharacterClass eClass = Characters.ClassObjects.ocCharacter.GetClassEnumeration(sCharClass);
            Characters.ClassObjects.ocCharacter oChar;
            
            switch (eClass) {
                case Characters.ClassObjects.ocCharacter.eCharacterClass.Barbarian:
                    oChar = new Characters.ClassObjects.ocBarbarian();
                    break;
                case Characters.ClassObjects.ocCharacter.eCharacterClass.Crusader:
                    oChar = new Characters.ClassObjects.ocCrusader();
                    break;
                case Characters.ClassObjects.ocCharacter.eCharacterClass.Demon_Hunter:
                    oChar = new Characters.ClassObjects.ocDemonHunter();
                    break;
                case Characters.ClassObjects.ocCharacter.eCharacterClass.Monk:
                    oChar = new Characters.ClassObjects.ocMonk();
                    break;
                case Characters.ClassObjects.ocCharacter.eCharacterClass.Witch_Doctor:
                    oChar = new Characters.ClassObjects.ocWitchDoctor();
                    break;
                case Characters.ClassObjects.ocCharacter.eCharacterClass.Wizard:
                    oChar = new Characters.ClassObjects.ocWizard();
                    break;
                default:
                    oChar = new Characters.ClassObjects.ocCharacter();
                    break;
            }
            oChar.sName = sCharName;
            oChar.eClass = eClass;

            if (oCharacterManager.AddNewCharacter(oChar)) {
                oNewCharacterWindow.Close();
                oSelectedCharacter = oChar;
                // reload
                do_UpdateGUICharacterList(true);
            }
            else {
                System.Windows.MessageBox.Show("Error creating new character.\nTry a different name.", "D3Crft", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
            }
        }

        private void ev_oNewCharacterWindow_Unloaded(object sender, EventArgs ea) {
            oMainWindow.QueueShadowOverlay(-1);
        }

        private void ev_oLoadingWindow_Unloaded(object sender, EventArgs ea) {
            flag_ForwardCharacterManagerInfoToLoadingWindow = false;
            if (flag_StartupRoutineInProgress) {
                flag_StartupRoutineInProgress = false;
                do_FinishStartupRoutine();
            }
        }

        private void ev_oStatChooserWindow_Unloaded(object sender, EventArgs ea) {
            oMainWindow.QueueShadowOverlay(-1);
            oStatChooserWindow = null;
        }

        #endregion

        // ####################################################
        // #####    Events
        // ####################################################
        #region Events

        // Other Objects

        private void ev_oCharacterManager_CharacterLoadProcess_Started(int iTotalCharCount, int iCurrentCharCount, string sFilename) {
            if (flag_ForwardCharacterManagerInfoToLoadingWindow) {
                oLoadingWindow.AddProgressInfo("Loading characters ...", "", 20, 10.0f);
            }
        }

        private void ev_oCharacterManager_CharacterLoadProcess_PreloadUpdate(int iTotalCharCount, int iCurrentCharCount, string sFilename) {
            string[] sTemp = sFilename.Split('\\');
            if (flag_ForwardCharacterManagerInfoToLoadingWindow) {
                oLoadingWindow.AddProgressInfo("Loading character '" + sTemp[sTemp.GetUpperBound(0)] + "' ...", iCurrentCharCount.ToString() + " / " + iTotalCharCount.ToString(), 20, ((100.0f - 20.0f) / (float)iTotalCharCount) * (float)iCurrentCharCount);
            }
        }

        private void ev_oCharacterManager_CharacterLoadProcess_PostloadUpdate(int iTotalCharCount, int iCurrentCharCount, string sFilename) {
            string[] sTemp = sFilename.Split('\\');
            if (flag_ForwardCharacterManagerInfoToLoadingWindow) {
                oLoadingWindow.AddProgressInfo("Loaded character '" + sTemp[sTemp.GetUpperBound(0)] + "' !", iCurrentCharCount.ToString() + " / " + iTotalCharCount.ToString(), 30, (((100.0f - 20.0f) / (float)iTotalCharCount) * (float)iCurrentCharCount) + 5.0f);
            }
        }

        private void ev_oCharacterManager_CharacterLoadProcess_Finished(int iTotalCharCount, int iCurrentCharCount, string sFilename) {
            oLoadingWindow.AddProgressInfo(iTotalCharCount.ToString() + " character(s) loaded !", "", 30, 100.0f);
            oLoadingWindow.AddFinalization();
        }




        #endregion
    }
}
